package cn.sstir.hackathon.service;

import cn.sgst.tool.common.util.ToolUtil;
import cn.sstir.hackathon.core.ExportType;
import cn.sstir.hackathon.core.PatentExportMap;
import cn.sstir.hackathon.core.csv.CsvUtil;
import cn.sstir.hackathon.core.page.PageResult;
import cn.sstir.hackathon.core.poi.ExcelUtil;
import cn.sstir.hackathon.core.search.PatentQuery;
import cn.sstir.hackathon.core.tsv.TsvUtil;
import cn.sstir.hackathon.wrapper.PatentWrapper;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @author: fli
 * @email: fli@sstir.cn
 * @date: 2020/1/16 15:35
 */
@Service
public class PatentService {

    private static final String INDEXNAME = "patent_cn_v1";
    private static final String TYPENAME = "zl_cn";

    @Autowired
    private TransportClient client;

    @SuppressWarnings("unchecked")
    public PageResult search(PatentQuery patentQuery) throws Exception{
        // 创建search请求
        SearchRequest searchRequest = new SearchRequest(INDEXNAME).types(TYPENAME);
        // 实例化查询构造器
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 关键词查询
        String keyword = patentQuery.getKeyword();
        BoolQueryBuilder searchBoolQuery = QueryBuilders.boolQuery();
        if(ToolUtil.isNotEmpty(keyword)){
            searchBoolQuery.should(QueryBuilders.matchQuery("abstract.text_zh",keyword))
                            .should(QueryBuilders.matchQuery("abstract.text_en",keyword))
                    .should(QueryBuilders.matchQuery("title.text_zh",keyword))
                    .should(QueryBuilders.matchQuery("title.text_en",keyword))
                    .should(QueryBuilders.termQuery("inventors.name_zh.keyword",keyword).boost(5))
                    .should(QueryBuilders.termQuery("inventors.name_en.keyword",keyword).boost(5))
                    .should(QueryBuilders.matchQuery("applicants.name_zh.keyword",keyword).boost(5))
                    .should(QueryBuilders.termQuery("inventors.name_en.keyword",keyword).boost(5))
                    .should(QueryBuilders.prefixQuery("appno",keyword).boost(5))
                    .minimumShouldMatch(1);
        }
        sourceBuilder.query(searchBoolQuery);

        // 高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder().preTags("<font color='#7492AC'>")
                .postTags("</font>").numOfFragments(0);
        highlightBuilder.field("title.text_zh");
        sourceBuilder.highlighter(highlightBuilder);

        // 分页
        Integer pageNo = patentQuery.getPageNo();
        Integer pageSize = patentQuery.getPageSize();
        sourceBuilder.from((pageNo - 1) * pageSize).size(pageSize);

        searchRequest.source(sourceBuilder);

        // 发送请求
        SearchResponse searchResponse = client.search(searchRequest).get();
        // 处理结果
        SearchHits hits = searchResponse.getHits();
        List<Map<String,Object>> records = new ArrayList<>();
        for (SearchHit hit : hits) {
            Map<String, Object> source = hit.getSourceAsMap();
            // 处理高亮数据
            Map<String, HighlightField> highlightMap = hit.getHighlightFields();
            if(highlightMap.get("title.text_zh") != null){
                source.put("title.text_zh",highlightMap.get("title.text_zh").getFragments()[0].toString());
            }
            records.add(source);
        }

        PageResult pageResult = new PageResult(pageNo, pageSize, hits.getTotalHits());
        pageResult.setRecords(records);
        return new PatentWrapper(pageResult).wrap();
    }


    /**
     * 专利导出
     *
     * @author fli
     * @date 2020/1/17 0:35
     */
    public void export(HttpServletResponse response, List<String> columns, PatentQuery patentQuery, ExportType exportType) throws Exception{
        // 创建search请求
        SearchRequest searchRequest = new SearchRequest(INDEXNAME).types(TYPENAME);
        // 实例化查询构造器
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 关键词查询
        String keyword = patentQuery.getKeyword();
        BoolQueryBuilder searchBoolQuery = QueryBuilders.boolQuery();
        if(ToolUtil.isNotEmpty(keyword)){
            searchBoolQuery.should(QueryBuilders.matchQuery("abstract.text_zh",keyword))
                    .should(QueryBuilders.matchQuery("abstract.text_en",keyword))
                    .should(QueryBuilders.matchQuery("title.text_zh",keyword))
                    .should(QueryBuilders.matchQuery("title.text_en",keyword))
                    .should(QueryBuilders.termQuery("inventors.name_zh.keyword",keyword).boost(5))
                    .should(QueryBuilders.termQuery("inventors.name_en.keyword",keyword).boost(5))
                    .should(QueryBuilders.matchQuery("applicants.name_zh.keyword",keyword).boost(5))
                    .should(QueryBuilders.termQuery("inventors.name_en.keyword",keyword).boost(5))
                    .should(QueryBuilders.prefixQuery("appno",keyword).boost(5))
                    .minimumShouldMatch(1);
        }
        sourceBuilder.query(searchBoolQuery);
        sourceBuilder.fetchSource(columns.toArray(new String[columns.size()]),null);
        sourceBuilder.from(0).size(1000);
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest).get();
        // 处理结果
        SearchHits hits = searchResponse.getHits();
        List<Map<String,Object>> records = new ArrayList<>();
        for (SearchHit hit : hits) {
            Map<String, Object> source = hit.getSourceAsMap();
            records.add(source);
        }

        records = new PatentWrapper(records).wrap();

        if(exportType == null){
            throw new IllegalArgumentException("ExportType must not be null");
        }

        if(exportType == ExportType.excel){
            ExcelUtil.exportExcel(PatentExportMap.class,columns,response,records,UUID.randomUUID().toString(),"专利搜索结果导出","专利");
        }

        if(exportType == ExportType.csv){
            CsvUtil.exportCsv(PatentExportMap.class,columns,records,true,UUID.randomUUID().toString(),response);
        }

        if(exportType == ExportType.tsv){
            TsvUtil.exportTsv(PatentExportMap.class,columns,records,UUID.randomUUID().toString(),response);
        }





    }
}
